package cn.bytepulse.web.auth.service.impl;

import cn.bytepulse.constant.HttpStatus;
import cn.bytepulse.pojo.AjaxResult;
import cn.bytepulse.utils.JWTUtils;
import cn.bytepulse.utils.RedisUtils;
import cn.bytepulse.utils.ReqUtils;
import cn.bytepulse.web.admin.entity.SysUser;
import cn.bytepulse.web.admin.mapper.SysUserMapper;
import cn.bytepulse.web.auth.dao.LoginUser;
import cn.bytepulse.web.auth.params.LoginParam;
import cn.bytepulse.web.auth.service.AuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author jiejiebiezheyang
 * @since 2024-03-03 11:00
 */
@Service
@Transactional
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final AuthenticationManager authenticationManager;

    private final RedisUtils redisUtils;

    private final SysUserMapper sysUserMapper;

    /**
     * 登录
     */
    @Override
    public AjaxResult login(LoginParam loginParam) {
        // 使用authenticate进行认证
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(loginParam.getUsername(), loginParam.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authentication);
        // 认证没通过,给出提示
        if (authenticate == null) {
            return AjaxResult.error(HttpStatus.LOGIN_ERROR);
        }
        Map<String, Object> map = new HashMap<>();
        // 认证通过
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        SysUser user = loginUser.getSysUser();
        user.setPassword(null);
        map.put("user_id", user.getId());
        map.put("nickname", user.getNickname());
        map.put("last_login", user.getLastLogin());
        map.put("last_login_ip", user.getLastLoginIp());
        // 更新登录记录
        user.setLastLoginIp(ReqUtils.getIP());
        user.setLastLogin(new Date());
        sysUserMapper.updateById(user);
        // 生成UUID作为token指纹
        String fingerprint = UUID.randomUUID().toString();
        user.setPassword(fingerprint);
        // 使用 userId 和 角色 生成token,返回token
        String userId = String.valueOf(loginUser.getSysUser().getId());
        JWTUtils.Payload payload = new JWTUtils.Payload();
        payload.with("userId", userId).with("fingerprint", fingerprint);
        String token = JWTUtils.createToken(payload, 24 * 60);
        // 把用户信息存入redis
        redisUtils.setCacheObject("login:" + userId, loginUser, 15L * 60L, TimeUnit.SECONDS);
        // 返回token给前端
        map.put("token", token);
        return AjaxResult.success(map);
    }

    /**
     * 登录状态测试
     */
    @Override
    public AjaxResult ping() {
        return AjaxResult.success();
    }
}
